<!-- 流程管理-实验模板管理-新增或编辑模板信息 -->
<template>
  <div class="main-app" v-loading="loading">
    <el-breadcrumb separator-class="el-icon-arrow-right" style="margin-top: 5px; margin-bottom: 15px;">
      <el-breadcrumb-item :to="{path:'/'}">{{$t('common.nav.home')}}</el-breadcrumb-item>
      <el-breadcrumb-item>{{$t('common.nav.flowManage')}}</el-breadcrumb-item>
      <el-breadcrumb-item>{{$t('common.nav.experimentTemplateManage')}}</el-breadcrumb-item>
      <el-breadcrumb-item>{{$t('common.nav.editExperimentTemplate')}}</el-breadcrumb-item>
    </el-breadcrumb>
    <el-row :gutter="10">
      <!-- 组件库区 -->
      <el-col :span="5">
        <el-card shadow="hover" class="box-card" style="height: 88vh; overflow-y: scroll;">
          <div class="titie-bar"><span>{{$t('common.title.componentLibrary')}}</span></div>
          <div v-loading="loading_assembly">
            <div style="font-size: 14px; padding-top: 6px; text-align: center;">
              <el-switch
                v-model="expandAllAssembly"
                @change="changeExpandAllAssembly"
                :inactive-text="$t('common.label.foldAllPanal')"
                :active-text="$t('common.label.expandAllPanal')"
              ></el-switch>
            </div>
            <el-collapse v-model="activeAssemblyNames" style="margin-top: 15px;">
              <el-collapse-item v-for="item in assemblyData" :key="item.cnName"
                :label="languages === 'zh_CN' ? item.cnName : item.enName"
                :title="languages === 'zh_CN' ? item.cnName : item.enName"
                :name="languages === 'zh_CN' ? item.cnName : item.enName"
              >
                <el-row :gutter="5">
                  <el-col :span="12" v-for="node in item.assemblyList" :key="node.cnName"
                    :label="languages === 'zh_CN' ? node.cnName : node.enName"
                    :value="languages === 'zh_CN' ? node.cnName : node.enName"
                  >
                    <div draggable="true"
                      @drag="menuDrag('otherImage', {
                        tag: node.cnName,
                        label: languages === 'zh_CN' ? node.cnName : node.enName,
                        xlinkHref: node.imgSrcType === '10' ? require('../../../assets/icon'+node.imgSrc) : node.imgSrc
                      })" class="assembly-main">
                      <img :src="node.imgSrcType === '10' ? require('../../../assets/icon'+node.imgSrc) : node.imgSrc">
                      <div>{{languages === 'zh_CN' ? node.cnName : node.enName}}</div>
                    </div>
                  </el-col>
                </el-row>
              </el-collapse-item>
            </el-collapse>
          </div>
        </el-card>
      </el-col>
      <!-- 组件编辑区 -->
      <el-col :span="14">
        <el-card shadow="hover" class="box-card" style="height: 88vh; overflow: auto;">
          <div class="antv-content">
            <div class="antv-wrapper" v-loading="loading_expProcessOverview">
              <div class="wrapper-canvas" :style="{height: height}" id="wrapper" @drop="drop($event)" @dragover.prevent></div>
              <div class="wrapper-tips">
                <div class="wrapper-tips-item">
                  <el-switch v-model="isPortsShow" @change="changePortsShow"></el-switch>
                  <span>{{$t('common.label.isPortsShow')}}{{isPortsShow === false ? $t('common.label.close') : $t('common.label.open')}}</span>
                </div>
                <div class="wrapper-tips-item" style="margin-left: 20px;">
                  <el-switch v-model="autoLayoutMode" @change="changeAutoLayoutMode"></el-switch>
                  <span>{{$t('common.label.autoLayoutMode')}}: {{autoLayoutMode === false ? $t('common.label.singleTask') : $t('common.label.iterationOptimizeTask')}}</span>
                </div>
              </div>
            </div>
            <!-- 组件基本信息编辑区 -->
            <el-drawer title="" direction="rtl" :visible.sync="editDrawer">
              <div v-if="editDrawer" class="edit-main">
                <div class="edit-main-title">
                  <h3>{{editTitle}}</h3>
                  <i class="el-icon-close" @click="closeEditForm"></i>
                </div>
                <div v-if="editTitle === $t('common.label.editNode')" class="form-main">
                  <el-form ref="nodeForm" :model="form" label-width="80px">
                    <el-form-item :label="$t('common.label.nodeText')">
                      <el-input v-model="form.labelText" size="small" @input="changeNode('labelText', form.labelText)"></el-input>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.fontSize')">
                      <el-input v-model="form.fontSize" size="small" @input="changeNode('fontSize', form.fontSize)"></el-input>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.fontColor')">
                      <el-color-picker v-model="form.fontFill" @change="changeNode('fontFill', form.fontFill)"></el-color-picker>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.nodeBackground')">
                      <el-color-picker v-model="form.fill" @change="changeNode('fill', form.fill)"></el-color-picker>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.borderColor')">
                      <el-color-picker v-model="form.stroke" @change="changeNode('stroke', form.stroke)"></el-color-picker>
                    </el-form-item>
                     <div class="see-box">
                        <h5>{{$t('common.label.preview')}}</h5>
                        <div class="see-item" :style="{ 'background': form.fill, 'color': form.fontFill, 'border-color': form.stroke, 'font-size': form.fontSize + 'px' }">{{form.labelText}}</div>
                      </div>
                  </el-form>
                </div>
                <div v-if="editTitle === $t('common.label.editImgNode')" class="form-main">
                  <el-form ref="imageForm" :model="form" label-width="80px">
                    <el-form-item :label="$t('common.label.nodeText')">
                      <el-input v-model="form.labelText" size="small" @input="changeImageNode('labelText', form.labelText)"></el-input>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.fontColor')">
                      <el-color-picker v-model="form.labelFill" @change="changeImageNode('labelFill', form.labelFill)"></el-color-picker>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.nodeBackground')">
                      <el-color-picker v-model="form.fill" @change="changeImageNode('fill', form.fill)"></el-color-picker>
                    </el-form-item>
                    <!-- <el-form-item label="图片地址">
                      <el-input v-model="form.xlinkHref" size="small" placeholder="图片地址" @input="changeImageNode('xlinkHref', form.xlinkHref)"></el-input>
                      <el-image :src="form.xlinkHref" style="width: 80px; height: 80px; background: #f2f2f2" fit="fill"></el-image>
                    </el-form-item>
                    <el-form-item label="图片尺寸">
                      <div><span style="font-size: 14px; padding-right: 5px; color: #888;">宽</span><el-input-number v-model="form.width" :min="0" label="宽" size="mini" @change="changeImageNode('width', form.width)"></el-input-number></div>
                      <div><span style="font-size: 14px; padding-right: 5px; color: #888;">高</span><el-input-number v-model="form.height" :min="0" label="高" size="mini" @change="changeImageNode('height', form.height)"></el-input-number></div>
                    </el-form-item> -->
                  </el-form>
                </div>
                <div v-if="editTitle === $t('common.label.editConnection')" class="form-main">
                  <el-form ref="edgeForm" :model="form" label-width="80px">
                    <el-form-item :label="$t('common.label.labelContent')">
                      <el-input v-model="form.label" size="small" :placeholder="$t('common.placeholder.labelText')" @input="changeEdgeLabel(form.label, labelForm.fontColor, labelForm.fill, labelForm.stroke)"></el-input>
                      <div v-if="form.label" class="label-style">
                        <p>{{$t('common.label.fontColor')}}：<el-color-picker v-model="labelForm.fontColor" size="mini" @change="changeEdgeLabel(form.label, labelForm.fontColor, labelForm.fill, labelForm.stroke)"></el-color-picker></p>
                        <p>{{$t('common.label.backgroundColor')}}：<el-color-picker v-model="labelForm.fill" size="mini" @change="changeEdgeLabel(form.label, labelForm.fontColor, labelForm.fill, labelForm.stroke)"></el-color-picker></p>
                        <p>{{$t('common.label.strokeColor')}}：<el-color-picker v-model="labelForm.stroke" size="mini" @change="changeEdgeLabel(form.label, labelForm.fontColor, labelForm.fill, labelForm.stroke)"></el-color-picker></p>
                      </div>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.lineColor')">
                      <el-color-picker v-model="form.stroke" size="small" @change="changeEdgeStroke"></el-color-picker>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.lineStyle')">
                      <el-select v-model="form.connector" size="small" :placeholder="$t('common.placeholder.pleaseSelect')" @change="changeEdgeConnector">
                        <el-option :label="$t('common.label.rightAngle')" value="normal"></el-option>
                        <el-option :label="$t('common.label.roundedAngle')" value="rounded"></el-option>
                        <el-option :label="$t('common.label.smooth')" value="smooth"></el-option>
                        <el-option :label="$t('common.label.jumpover')" value="jumpover"></el-option>
                      </el-select>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.lineWidth')">
                      <el-input-number v-model="form.strokeWidth" size="small" @change="changeEdgeStrokeWidth" :min="2" :step="2" :max="6" label="线条宽度"></el-input-number>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.doubleArrows')">
                      <el-switch v-model="form.isArrows" @change="changeEdgeArrows"></el-switch>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.flowingLines')">
                      <el-switch v-model="form.isAnit" @change="changeEdgeAnit"></el-switch>
                    </el-form-item>
                    <el-form-item :label="$t('common.label.adjustingLines')">
                      <el-switch v-model="form.isTools" @change="changeEdgeTools"></el-switch>
                    </el-form-item>
                  </el-form>
                </div>
                <div class="edit-btn">
                  <el-button type="danger" @click="handlerDel" style="width:100%">{{$t('common.button.delNode')}}</el-button>
                </div>
              </div>
            </el-drawer>
          </div>
        </el-card>
      </el-col>
      <!-- 基本信息编辑区 -->
      <el-col :span="5">
        <el-card shadow="hover" class="box-card" style="height: 88vh; overflow: auto;">
          <div class="titie-bar"><span>{{$t('common.title.basicInformation')}}</span></div>
          <div style="padding: 10px;">
            <el-form ref="form" :model="basicform" :rules="rules" label-position="top">
              <el-form-item :label="$t('common.label.expTemplateName')+':'" prop="templateName" required>
                <el-input v-model="basicform.templateName" />
              </el-form-item>
              <el-form-item :label="$t('common.label.expTemplateNumber')+':'" prop="number" required>
                <el-input v-model="basicform.number" />
              </el-form-item>
              <el-form-item :label="$t('common.label.expTemplateAuth')+':'" required>
                <el-select v-model="basicform.type" :placeholder="$t('common.placeholder.pleaseSelect')" style="width: 100%">
                  <el-option :label="$t('common.label.public')" value="10" />
                  <el-option :label="$t('common.label.private')" value="20" />
                </el-select>
              </el-form-item>
              <el-form-item :label="$t('common.label.expType')+':'" required>
                <el-select v-model="basicform.taskType" :placeholder="$t('common.placeholder.pleaseSelect')" style="width: 100%" @change="expTemplateChange">
                  <el-option :label="$t('common.label.singleTask')" value="10" />
                  <el-option :label="$t('common.label.parallelTask')" value="20" disabled />
                  <el-option :label="$t('common.label.iterationOptimizeTask')" value="30" />
                </el-select>
              </el-form-item>
              <el-form-item :label="$t('common.label.expectedWorkingHours')+':'" prop="expectedWorkingHours" required>
                <el-input type="number" v-model="basicform.expectedWorkingHours" disabled />
              </el-form-item>
            </el-form>
          </div>
          <div class="wrapper-btn" v-if="loading_expProcessOverview === false">
            <el-row>
              <el-button type="primary" @click="handlerSend">{{$t('common.button.save')}}</el-button>
            </el-row>
            <el-row style="margin-top: 10px;">
              <el-button type="primary" plain @click="refresh">{{$t('common.button.clearEditingArea')}}</el-button>
            </el-row>
            <el-row style="margin-top: 10px;">
              <el-button @click="cancel">{{$t('common.button.back')}}</el-button>
            </el-row>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 提示框-组件属性配置 -->
    <el-dialog :title="$t('common.title.attributeConfig')" width="60%" style="margin-top: -2%;" :visible.sync="dialogVisibleConfig.attributeConfig">
      <div slot="title" style="background: #369BA5; color: white">
        <div style="padding: 15px 20px">{{$t('common.title.attributeConfig')}}</div>
      </div>
      <span slot="footer" class="dialog-footer">
        <div style="height: 550px; font-size: 18px; text-align: left; margin-top: -4%; overflow-y: scroll;">
          <el-form v-if="isDialogFormLoaded === true" :model="dialogForm.attributeConfig" ref="dialogForm.attributeConfig" label-width="120px">
            <!-- 固定显示工作时长 -->
            <el-form-item :label="$t('common.label.workingHours')">
              <el-input-number v-model="dialogForm.attributeConfig.workingHours" :placeholder="$t('common.placeholder.workingHours')" :min="0" style="width: 94.5%;"></el-input-number>
            </el-form-item>
            <!-- 遍历加载表单项内容 -->
            <el-form-item v-for="(field, index) in dialogFormFields" :key="index" :label="field.label" style="width: 95%;">
              <!-- <component style="width: 90%; margin-left: 30px;"
                :is="getFieldComponent(field.type)"
                :value="dialogForm.attributeConfig[field.name]"
                :placeholder="field.placeholder"
                :data="field.data"
                @input="updateFormData(index, $event.target.value)"
              >
              </component> -->
              <!-- 文本框内容 -->
              <el-input v-if="field.type==='text'" v-model="dialogForm.attributeConfig[field.name]" :placeholder="field.placeholder"></el-input>
              <!-- 数值框内容 -->
              <el-input-number v-if="field.type==='number'" v-model="dialogForm.attributeConfig[field.name]" :placeholder="field.placeholder" :min="0" style="width: 100%;"></el-input-number>
              <!-- 下拉框内容 -->
              <el-select v-if="field.type==='select'" v-model="dialogForm.attributeConfig[field.name]" :placeholder="field.placeholder" style="width: 100%;">
                <el-option v-for="item in field.data" :key="item.value" :label="item.label" :value="item.value" :disabled="item.disabled" />
              </el-select>
              <!-- 单选框内容 -->
              <el-radio-group v-if="field.type==='radio'" v-model="dialogForm.attributeConfig[field.name]" :placeholder="field.placeholder">
                <el-radio v-for="item in field.data" :key="item.value" :label="item.value" :value="model">{{item.label}}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-form>
        </div>
        <el-tooltip effect="dark" :content="$t('common.prompt.info.editNodeConfigTip')" placement="top">
          <el-button type="primary" plain @click="editForm(selectCell);dialogVisibleConfig.attributeConfig=false;">{{$t('common.button.editNodeConfig')}}</el-button>
        </el-tooltip>
        <el-button type="primary" @click="saveConfig();dialogVisibleConfig.attributeConfig=false">{{$t('common.button.determine')}}</el-button>
        <el-button @click="dialogVisibleConfig.attributeConfig=false">{{$t('common.button.cancel')}}</el-button>
      </span>
    </el-dialog>

  </div>
</template>

<script>
  import { Graph, Shape } from '@antv/x6';
  import { configSetting, configNodeShape, configNodePorts, configEdgeLabel, graphBindKey, assembly } from '@/utils/antvSetting';
  import {
    FlowAssemblyData,
  } from "../../../api/assembly.js";
  import {
    CreateExperimentNumber,
    ExperimentTemplateDetail,
    ExperimentTemplateConfigDetail,
    SubmitExperimentTemplateConfig,
    SubmitExperimentTemplate,
  } from "../../../api/experiment.js";

  // 引用表单组件
  import textInput from "./components/TextInput";
  import numberInput from "./components/NumberInput";
  import selectInput from "./components/SelectInput";
  import radioInput from "./components/RadioInput";

  export default {
    name: "AntV6X",
    /**
     * 这个是作为子组件分别接受了两个数据一个是高度height，一个是反显图表数据tempGroupJson
     * 作为子组件例子 <AntVXSix v-model="tempGroupJson" height="720px" />
     */
    props: {
      height: {
        type: String,
        default: '83vh' //'720px'
      },
      value: {
        type: String,
        default: ''
      }
    },
    components: {
      textInput,
      numberInput,
      selectInput,
      radioInput,
    },
    // 页面公共变量
    data() {
      return {
        // 基本配置
        languages: '',                // 当前语言
        templateid: "",               // 实验模板主键ID
        id: "",                       // 编辑数据的主键ID
        isDialogFormLoaded: false,    // 表单属性是否渲染完成

        // 加载框
        loading_assembly: false,               // 组件库
        loading_detail: false,                 // 基本信息
        loading_expProcessOverview: false,     // 实验流程概览

        expTemplateData: {},          // 实验模板数据
        expTemplateConfigData: {},    // 实验模板关联配置数据
        // 基本信息表单
        basicform:{
          type: '10',                 // 实验模板类型
          taskType: '10',             // 实验任务类型
          templateId: '',             // 实验模板ID
          templateName: 'Template',   // 实验模板名称
          number: '',                 // 实验模板编号
          expectedWorkingHours: 1,    // 实验预计工作时长
        },
        // 表单验证项配置
        rules: {
          name: [{required:true, message:this.$t('common.prompt.rules.expName'), trigger:"blur"}],
          number: [{required:true, message:this.$t('common.prompt.rules.expNumber'), trigger:"blur"}],
          sort: [{required:true, message:this.$t('common.prompt.rules.expSort'), trigger:"blur"}],
          expectedWorkingHours: [{required:true, message:this.$t('common.prompt.rules.expectedWorkingHours'), trigger:"blur"}],
        },

        // 提示框选项表单字段
        dialogFormFields: [],
        // 提示框选项表单
        dialogForm: {
          // 组件属性配置
          attributeConfig: {
            workingHours: 0,          // 工作时长
          },
        },
        // 提示框表单数据源
        dialogFormDataSource: {},
        // 已保存的提示框表单
        dialogSaveForm: [],
        // 提示框开关配置
        dialogVisibleConfig: {
          attributeConfig: false,     // 组件属性配置
        },

        // 组件库配置
        expandAllAssembly: false,     // 是否展开全部组件面板
        activeAssemblyNames: [],      // 当前激活的面板
        assemblyData: [],             // 组件库数据
        assemblyConfigData: [],       // 组件库配置数据

        // 组件编辑配置
        graph: null,                  // 组件编辑区容器
        isChange: false,              // 是否选中
        isPortsShow: false,           // 是否显示链接桩
        autoLayoutMode: false,        // 自动布局模式  true: 贝叶斯优化  false: 单任务
        menuItem: '',                 // 选择的菜单节点名称
        selectCell: '',               // 选择的节点
        editDrawer: false,            // 是否显示节点属性编辑区
        editTitle: '',                // 节点信息区标题
        form:{},                      // 组件信息表单
        // 文本信息表单
        labelForm: {
          fontColor: '#333',
          fill: '#FFF',
          stroke: '#555'
        },
        // 默认组件定位配置-单任务
        assemblyLocation: [
          // 第一行
          [80,70], [310,70], [540,70], [760,70],
          // 第二行
          [760,300], [540,300], [310,300], [80,300],
          // 第三行
          [80,530], [310,530], [540,530], [760,530],
        ],
        // 默认组件连线配置-单任务
        assemblyRouteConfig: [
          // 第一行：从左至右
          {startNodeIndex: 0, startPort: 'right', endNodeIndex: 1, endPort: 'left'},
          {startNodeIndex: 1, startPort: 'right', endNodeIndex: 2, endPort: 'left'},
          {startNodeIndex: 2, startPort: 'right', endNodeIndex: 3, endPort: 'left'},
          {startNodeIndex: 3, startPort: 'right', endNodeIndex: 4, endPort: 'left'},
          // 第二行：从右至左
          {startNodeIndex: 4, startPort: 'bottom', endNodeIndex: 5, endPort: 'top'},
          {startNodeIndex: 5, startPort: 'left', endNodeIndex: 6, endPort: 'right'},
          {startNodeIndex: 6, startPort: 'left', endNodeIndex: 7, endPort: 'right'},
          {startNodeIndex: 7, startPort: 'left', endNodeIndex: 8, endPort: 'right'},
          // 第三行：从左至右
          {startNodeIndex: 8, startPort: 'bottom', endNodeIndex: 9, endPort: 'top'},
          {startNodeIndex: 9, startPort: 'right', endNodeIndex: 10, endPort: 'left'},
          {startNodeIndex: 10, startPort: 'right', endNodeIndex: 11, endPort: 'left'},
          {startNodeIndex: 11, startPort: 'right', endNodeIndex: 12, endPort: 'left'},
        ],
        // 默认组件定位配置-迭代优化任务
        assemblyLocationBayes: [
          // 第一行
          [80,70], [310,70], [540,70], [760,70],
          // 第二行
          [760,300],
          // 第三行
          [760,530], [540,530], [310,530], [80,530],
          // 第二行
          [80,300],
        ],
        // 默认组件连线配置-迭代优化任务
        assemblyRouteConfigBayes: [
          // 第一行：从左至右
          {startNodeIndex: 0, startPort: 'right', endNodeIndex: 1, endPort: 'left'},
          {startNodeIndex: 1, startPort: 'right', endNodeIndex: 2, endPort: 'left'},
          {startNodeIndex: 2, startPort: 'right', endNodeIndex: 3, endPort: 'left'},
          {startNodeIndex: 3, startPort: 'right', endNodeIndex: 4, endPort: 'left'},
          // 第二行：从上至下
          {startNodeIndex: 4, startPort: 'bottom', endNodeIndex: 5, endPort: 'top'},
          // 第三行：从右至左
          {startNodeIndex: 5, startPort: 'bottom', endNodeIndex: 6, endPort: 'top'},
          {startNodeIndex: 6, startPort: 'left', endNodeIndex: 7, endPort: 'right'},
          {startNodeIndex: 7, startPort: 'left', endNodeIndex: 8, endPort: 'right'},
          {startNodeIndex: 8, startPort: 'left', endNodeIndex: 9, endPort: 'right'},
          // 第二行：从下至上
          {startNodeIndex: 9, startPort: 'top', endNodeIndex: 10, endPort: 'bottom'},
          {startNodeIndex: 10, startPort: 'top', endNodeIndex: 1, endPort: 'bottom'},
        ],
      }
    },
    watch:{
      value:{
        handler: function(){
          if(this.graph){
            this.isChange = false
            this.isPortsShow = false
            this.menuItem = ''
            this.selectCell = ''
            this.editDrawer = false
            this.graph.dispose()
            this.initGraph()
          }
        },
        deep: true,
        immediate: true
      }
    },
    // 缓存值
    computed: {
      // 默认值表单
      dialogDefaultForm() {
        // 将源变量复制到新变量中
        return JSON.parse(JSON.stringify(this.dialogForm));
      },
    },
    // 页面创建完成事件
    async created() {
      // 接收路由传递的参数
      const { templateid, id, type } = this.$route.params;

      // 将接收到的数据填充至页面公共变量
      this.templateid = templateid;
      this.id = id;
      this.basicform.taskType = type;

      // 当前编辑的类型为迭代优化时将自动选中
      if (type === "30") {
        this.autoLayoutMode = true;
      }

      this.languages = localStorage.getItem('language') || 'zh_CN';

      // 初始化
      this.init();
    },
    // 实例挂载完成事件
    mounted() {
      //this.init();
      this.initGraph();
    },
    beforeDestroy() {
      this.graph.dispose();
    },
    // 页面相关方法
    methods: {
      // ======================================== 基本信息相关 ========================================

      // 刷新当前页面
      refresh() {
        this.$confirm(this.$t('common.prompt.info.isRefresh'), this.$t('common.dialog.tip'), {
          confirmButtonText: this.$t('common.dialog.confirm'),
          cancelButtonText: this.$t('common.dialog.cancel'),
          type: 'warning'
        }).then(() => {
          this.graph.clearCells();    // 清空全部节点
          //this.basicform = {};        // 清空基本信息表单内容
          this.editDrawer = false;    // 关闭组件编辑区
          //this.$router.go(0);
        }).catch(() => {
          //this.$message({type: 'info', message: '已取消重置操作'});
        });
      },
      // 获取静态图片资源
      getImgSrc(url) {
        return require(url);
      },
      // 初始化页面数据
      async init() {
        // 获取组件库配置数据
        this.loading_assembly = true;
        await FlowAssemblyData({}).then((res) => {
          this.loading_assembly = false;
          if (res.success === true) {
            this.assemblyData = res.data;
            this.assemblyData.forEach(item => {
              item.assemblyList.forEach(itemSon => {
                this.assemblyConfigData.push(itemSon);
              });
            });
          }
        });

        // 标识正在加载表单数据
        this.isDialogFormLoaded = false;

        // 如果当前传入主键ID时则查询详情信息
        if (this.id != undefined) {
          // 获取详情数据
          await this.getDataInfo();
        } else {
          // 初始化实验任务编号
          await CreateExperimentNumber().then((res) => {
            this.basicform.number = res.data;
          });
        }
      },
      // 获取详情数据
      async getDataInfo() {
        this.$message({type: 'info', message: this.$t('common.prompt.info.templateConfigLoading'), duration: 5000, showClose: true});

        // 打开实验流程加载框
        this.loading_expProcessOverview = true;

        // 获取实验模板详情数据
        await ExperimentTemplateDetail({
          Id: this.templateid
        }).then((res) => {
          if (res.success === true) {
            this.expTemplateData = res.data;
            this.basicform.templateId = res.data.id;
            this.basicform.templateName = res.data.name;
            this.basicform.type = res.data.type;
            this.basicform.number = res.data.number;
          }
        });

        // 获取详情数据
        const { data, data2 } = await ExperimentTemplateConfigDetail({
          Id: this.id
        });
        if (data !== null) {
          // 设置表单数据
          this.expTemplateConfigData = data;
          this.basicform.taskType = data.type;
          //this.basicform.expectedWorkingHours = parseInt(data.expectedWorkingHours);
          //this.dialogSaveForm = data2;
          this.dialogSaveForm = JSON.parse(data.assemblyConfig);

          // 重新统计预计工作时长
          this.reStatisticsExpectedWorkingHours();

          // 初始化流程配置
          this.graph.clearCells();    // 清空全部节点
          const flowPathConfigData = eval(data.flowPathConfig);
          this.graph.fromJSON(flowPathConfigData);

          // 关闭实验流程加载框
          this.loading_expProcessOverview = false;

          this.$message({type: 'success', message: this.$t('common.prompt.success.templateConfigLoading')});
        } else {
          // 关闭实验流程加载框
          this.loading_expProcessOverview = false;

          this.$message({type: 'info', message: this.$t('common.prompt.info.notHaveTemplateConfig')});
        }
      },

      // ======================================== 提示框组件参数编辑相关 ========================================

      // 根据类型返回对应的组件名
      getFieldComponent(type) {
        return `${type}Input`;
      },
      // 更新表单数据对象中的值
      updateFormData(index, value) {
        this.$set(this.dialogForm.attributeConfig, this.dialogFormFields[index].name, value);
        console.log(this.dialogForm.attributeConfig);
      },
      // 重置表单
      resetForm(formName) {
        this.$refs[formName].resetFields();
      },

      // ======================================== 组件编辑相关 ========================================

      // 是否展开全部组件事件
      changeExpandAllAssembly(val) {
        if (val === true) {
          // 激活右侧组件库全部面板
          this.assemblyData.map(item => {
            this.activeAssemblyNames.push(item.cnName);
          });
        } else {
          // 取消激活右侧组件库全部面板
          this.activeAssemblyNames = [];
        }
      },
      // 链接桩的显示与隐藏，主要是照顾菱形
      changePortsShow(val) {
        const container = document.getElementById('wrapper');
        const ports = container.querySelectorAll('.x6-port-body');
        for (let i = 0, len = ports.length; i < len; i = i + 1) {
          ports[i].style.visibility = val ? 'visible' : 'hidden';
        }
      },
      // 初始化渲染画布
      initGraph() {
        const graph = new Graph({
          container: document.getElementById('wrapper'),
          ...configSetting(Shape)
        });

        // 画布事件
        graph.on('node:mouseenter', () => { this.changePortsShow(true); });
        graph.on('node:mouseleave', () => { if(this.isPortsShow) return; this.changePortsShow(false); });

        // 点击编辑
        //graph.on('cell:click', ({cell}) => { this.editForm(cell); });
        graph.on('cell:click', ({cell}) => { this.editConfig(cell); });

        // 画布键盘事件
        graphBindKey(graph);

        // 删除
        graph.on('cell:contextmenu', ({cell}) => { this.handlerDel(); });
        graph.bindKey(['delete','backspace'], () => { this.handlerDel(); });

        // 赋值
        this.graph = graph;

        // 返现方法
        if(this.value && JSON.parse(this.value).length) {
          const resArr = JSON.parse(this.value);
          // 导出的时候删除了链接桩设置加回来
          const portsGroups = configNodePorts().groups;
          if(resArr.length) {
            const jsonTemp = resArr.map(item => {
              if(item.ports) item.ports.groups = portsGroups
              return item;
            });
            graph.fromJSON(jsonTemp);
          }
        }

        // 画布有变化
        graph.on('cell:changed', () => { this.isChangeValue(); });
      },
      // 画布是否有变动
      isChangeValue() {
        if(!this.isChange) {
          this.isChange = true;
          this.$emit('cellChanged', true);
        }
      },
      // 根据type获取到不同节点的预设参数
      menuDrag(type, param) {
        this.menuItem = configNodeShape(type, param);
      },
      // 节点预设 ，添加位置信息和链接桩信息组合成完整的节点
      drop(event) {
        let nodeItem = {
          ...this.menuItem,
          size: {
            width: 100,
            height: 100
          },
          x: event.offsetX - (this.menuItem.width / 2),
          y: event.offsetY - (this.menuItem.height / 2),
          ports: configNodePorts(),
          createTime: new Date().toLocaleString()
        }
        //console.log(nodeItem);

        // 检查当前是否已存在贝叶斯优化节点，如果已存在时则无法继续添加节点
        if (this.checkBayesNode() === true) {
          this.$message({type: 'error', message: this.$t('common.prompt.error.unableAddNode')});
          return;
        }

        // 组件自动布局
        if (this.autoLayoutMode === true) {
          if (this.getImgNodeData().length < 10) {
            let location = this.calculateLocation();
            nodeItem.x = location[0];
            nodeItem.y = location[1];
          }
        } else {
          if (this.getImgNodeData().length < 12) {
            let location = this.calculateLocation();
            nodeItem.x = location[0];
            nodeItem.y = location[1];
          }
        }

        // 创建节点
        this.graph.addNode(nodeItem);
        this.isChangeValue();

        // 添加连接线
        this.setEdge(this.getImgNodeData().length);

        // 当前节点为贝叶斯优化时则添加终止连接线
        if (nodeItem.attrs.label.tag === '贝叶斯优化') {
          this.setEndEdge();
        }
        // 当前为 迭代优化布局模式 并且 已经填满节点时 再添加一条结尾连接线
        else if (this.autoLayoutMode === true && this.getImgNodeData().length === 10) {
          this.setEdge(this.getImgNodeData().length + 1);
        }
      },
      // 计算节点位置
      calculateLocation() {
        if(this.autoLayoutMode === false) {
          return this.assemblyLocation[this.getImgNodeData().length];
        } else {
          return this.assemblyLocationBayes[this.getImgNodeData().length];
        }
      },
      // 添加节点连接线
      setEdge(index) {
        try {
          let imgNodeData = this.getImgNodeData();        // 图片节点数据
          //let routeIndex = imgNodeData.length;          // 图片节点数据长度
          let routeIndex = index;                         // 图片节点数据长度
          let routeConfig = this.autoLayoutMode === false ? this.assemblyRouteConfig[routeIndex - 1] : this.assemblyRouteConfigBayes[routeIndex - 1];

          let startNode = imgNodeData[routeConfig.startNodeIndex - 1];   // 源节点
          let endNode = imgNodeData[routeConfig.endNodeIndex - 1];       // 目标节点

          let startPort = startNode.port.ports.find(item => {return item.group === routeConfig.startPort});
          let endPort = endNode.port.ports.find(item => {return item.group === routeConfig.endPort});

          this.graph.addEdge({
            // 源节点 ID 和链接桩 ID
            source: {
              cell: startNode.id,
              port: startPort.id,
            },
            // 目标节点 ID 和链接桩 ID
            target: {
              cell: endNode.id,
              port: endPort.id,
            },
            // 连接线样式
            attrs: {
              line: {
                stroke: "#A2B1C3",    // 颜色
                strokeDasharray: 5,
                style: {
                  animation: 'ant-line 30s infinite linear',  // 动画
                }
              },
            },
          });
        } catch (ex) {
          // 异常可能为超出索引导致，不进行处理即可
        }
      },
      // 添加终点节点连接线
      setEndEdge() {
        try {
          let imgNodeData = this.getImgNodeData();        // 图片节点数据
          let routeIndex = imgNodeData.length;          // 图片节点数据长度
          let routeConfig = this.autoLayoutMode === false ? this.assemblyRouteConfig[routeIndex] : this.assemblyRouteConfigBayes[routeIndex];

          let startNode = imgNodeData[routeConfig.startNodeIndex - 1];   // 源节点
          let endNode = imgNodeData[0];       // 目标节点

          let startPort = startNode.port.ports.find(item => {return item.group === routeConfig.startPort});
          let endPort = endNode.port.ports.find(item => {return item.group === 'bottom'});

          this.graph.addEdge({
            // 源节点 ID 和链接桩 ID
            source: {
              cell: startNode.id,
              port: startPort.id,
            },
            // 目标节点 ID 和链接桩 ID
            target: {
              cell: endNode.id,
              port: endPort.id,
            },
            // 连接线样式
            attrs: {
              line: {
                stroke: "#A2B1C3",    // 颜色
                strokeDasharray: 5,
                style: {
                  animation: 'ant-line 30s infinite linear',  // 动画
                }
              },
            },
          });
        } catch (ex) {
          // 异常可能为超出索引导致，不进行处理即可
        }
      },
      // 刷新节点位置
      resetLocation() {
        // 获取图片节点
        let cells = this.getImgNodeData();

        // 将所有图片节点按照默认顺序重新排序
        let tmpLocation = [];
        for (let i = 0; i < cells.length; i++) {
          if (this.autoLayoutMode === true) {
            tmpLocation = this.assemblyLocationBayes[i];
            cells[i].position(tmpLocation[0], tmpLocation[1]);
          } else {
            tmpLocation = this.assemblyLocation[i];
            cells[i].position(tmpLocation[0], tmpLocation[1]);
          }
        }

        // 删除所有连接线节点
        this.delAllLineNode();

        // 对所有图片节点进行重新连线
        let routeConfig = [];
        for (let i = 0; i < cells.length; i++) {
          try {
            // 获取连线配置
            if (this.autoLayoutMode === true) {
              routeConfig = this.assemblyRouteConfigBayes[i];
            } else {
              routeConfig = this.assemblyRouteConfig[i];
            }

            // 获取源节点信息
            let startNode = cells[routeConfig.startNodeIndex - 1];
            // 获取目标节点信息
            let endNode = cells[routeConfig.endNodeIndex - 1];

            // 开始链接桩
            let startPort = startNode.port.ports.find(item => {return item.group === routeConfig.startPort});
            // 结束链接桩
            let endPort = endNode.port.ports.find(item => {return item.group === routeConfig.endPort});

            // 添加连线节点
            this.graph.addEdge({
              // 源节点 ID 和链接桩 ID
              source: {
                cell: startNode.id,
                port: startPort.id,
              },
              // 目标节点 ID 和链接桩 ID
              target: {
                cell: endNode.id,
                port: endPort.id,
              },
              // 连接线样式
              attrs: {
                line: {
                  stroke: "#A2B1C3",    // 颜色
                  strokeDasharray: 5,
                  style: {
                    animation: 'ant-line 30s infinite linear',  // 动画
                  }
                },
              },
            });
          } catch (ex) {
            // 异常可能为超出索引导致，不进行处理即可
          }
        }
      },
      // 删除全部线接线节点
      delAllLineNode() {
        var nodeArrays = this.graph.getCells().filter(function(item){
          return item.store.data.shape == 'edge';
        });
        this.graph.removeCells(nodeArrays);
      },
      // 检查贝叶斯优化节点是否存在
      checkBayesNode() {
        var nodeArrays = this.graph.getCells().filter(function(item){
          return item.label == '图片' && item.attrs.label.tag === '贝叶斯优化';
        });
        return nodeArrays.length > 0;
      },
      // 获取图片节点数据
      getImgNodeData() {
        var imgNodeArrays = this.graph.getCells().filter(function(item){
          return item.label == '图片';
        });
        return imgNodeArrays;
      },
      // 重新统计预计工作时长
      reStatisticsExpectedWorkingHours() {
        this.basicform.expectedWorkingHours = 0;
        let tmpNodeData = {};
        for (let i = 0; i < this.dialogSaveForm.length; i++) {
          tmpNodeData = this.dialogSaveForm[i];
          this.basicform.expectedWorkingHours += parseInt(tmpNodeData.workingHours);
        }
      },
      // 编辑节点参数
      editConfig(cell) {
        //console.log(cell.attrs.label.tag);
        this.selectCell = cell;                       // 存储当前选中的节点数据
        this.dialogForm = this.dialogDefaultForm;     // 重置表单默认值

        try {
          // 标识正在加载表单数据
          this.isDialogFormLoaded = false;

          // 获取当前节点可用的编辑属性数据
          let nodeConfigData = this.assemblyConfigData.find(item => item.cnName === cell.attrs.label.tag).attributeList;

          // 加载表单属性
          this.dialogFormFields = [];
          let tempType = '';
          let tempValue = null;
          let tempData = [];
          nodeConfigData.forEach(item => {
            // 转换输入类型
            switch (item.inputType) {
              case "10": { tempType = 'text'; } break;
              case "20": { tempType = 'number'; } break;
              case "30": { tempType = 'select'; } break;
              case "40": { tempType = 'radio'; } break;
            }

            // 转换参数类型
            switch (item.paramType) {
              case "10": { tempValue = item.defaultValue; } break;
              case "20": { tempValue = parseInt(item.defaultValue); } break;
              case "30": { tempValue = parseFloat(item.defaultValue); } break;
            }

            // 处理并填充表单项数据源内容
            if (item.inputDataSource !== null && item.inputDataSource !== "") {
              // 初始化数据源
              tempData = [];

              // 将字符串内容按指定符号分割为数组
              let dataSource = item.inputDataSource.split('||');

              // 循环遍历分割后数组内容
              let tempDataSource = [];
              let tempName = [];
              dataSource.forEach(item => {
                // 将当前循环节点按指定符号分割为数组
                tempDataSource = item.split('::');
                tempName = tempDataSource[0].split(';;');

                // 将当前循环节点内容填充至数据源
                tempData.push({
                  label: this.languages === 'zh_CN' ? tempName[0] : tempName[1],
                  value: tempDataSource[1],
                  disabled: false,
                });
              });
            }

            // 将英文名称转换为表单项的Key
            let formItemKey = this.toLowerCaseFirstLetter(item.enName).replace(' ', '');

            // 填充表单数据源数据
            this.dialogForm.attributeConfig[formItemKey] = tempValue;

            // 填充表单属性数据
            this.dialogFormFields.push({
              type: tempType,
              label: item.cnName,
              name: formItemKey,
              value: tempValue,
              placeholder: this.$t('common.placeholder.pleaseInput'),
              data: tempData
            });
          });

          // 标识表单数据加载完成
          this.isDialogFormLoaded = true;

          // 加载配置项目
          try {
            this.dialogForm.attributeConfig = this.dialogSaveForm.find(item => item.id === cell.id).data;
          } catch (ex) {}

          // 显示编辑弹窗
          this.dialogVisibleConfig.attributeConfig = true;
        } catch (ex) {
          console.log(ex);
          this.editForm(this.selectCell);
        }
      },
      // 保存节点参数
      saveConfig() {
        // 当前节点ID
        let nodeId = this.selectCell.id;

        // 当前节点详情
        let nodeData = this.dialogSaveForm.find(item => item.id == nodeId);

        // 查询不包含当前节点的表单配置数据，用于每次保存都是当前节点的最新配置
        let newConfigData = [];
        if(this.dialogSaveForm !== undefined) {
          newConfigData = this.dialogSaveForm.filter(function(item) { return item.id != nodeId; });
        }

        // 存储最新的配置数据
        let pushData = {
          id: nodeId,
          name: this.selectCell.attrs.label.tag,
          workingHours: `${this.dialogForm.attributeConfig.workingHours}`,
          data: this.dialogForm.attributeConfig,
        };

        // 初次保存时可能会没有此参数, 添加异常处理, 再次保存时会正常执行
        try {
          // 减去当前节点的时长
          this.basicform.expectedWorkingHours -= parseInt(nodeData.workingHours);
        } catch {}

        // 将当前节点设置的 工作时长 添加至 预计工作时长 内
        this.basicform.expectedWorkingHours += parseInt(pushData.workingHours);

        // 保存最新配置
        newConfigData.push(pushData);
        this.dialogSaveForm = newConfigData;
      },
      // 删除节点参数
      delConfig() {
        try {
          // 获取节点ID
          let nodeId = this.selectCell.id;

          // 预计工作时长 减去当前节点设置的 工作时长
          let nodeData = this.dialogSaveForm.find(item => item.id == nodeId);
          this.basicform.expectedWorkingHours -= parseInt(nodeData.workingHours);

          // 获取排除当前节点的最新配置数据并保存
          let newConfigData = this.dialogSaveForm.filter(function(item){
            return item.id != nodeId;
          });
          this.dialogSaveForm = newConfigData;
          //console.log(this.dialogSaveForm);
        } catch (ex) {}
      },
      // 删除多个节点参数
      delManyConfig(cell) {
        for (let i = 0; i < cell.length; i++) {
          try {
            this.selectCell = cell[i];
            this.delConfig();
          } catch (ex) {}
        }
      },
      // 点击编辑更具不同的内容获取编辑数据
      editForm(cell) {
        if(this.selectCell) this.selectCell.removeTools();            // 删除修改线的工具
        this.selectCell = cell;                                       // 存储当前选中的节点数据

        // 编辑node节点
        if(cell.isNode() && cell.data.type && cell.data.type.includes('default')) {
          this.editTitle = this.$t('common.label.editNode');
          const body = cell.attrs.body || cell.attrs.rect || cell.attrs.polygon || cell.attrs.circle;
          this.form = {
            labelText: cell.attrs.label.text || '',
            fontSize: cell.attrs.label.fontSize || 14,
            fontFill: cell.attrs.label.fill || '',
            fill: body.fill|| '',
            stroke: body.stroke || ''
          }
          return this.editDrawer = true;
        }
        // 编辑图片节点
        if(cell.isNode() && cell.data.type && cell.data.type === 'otherImage') {
          this.editTitle = this.$t('common.label.editImgNode');
          const attrs = cell.attrs || { body:{fill: ''}, label: {text: '', fill: ''}, image:{xlinkHref: '', height:  80, width: 80} }
          this.form = {
            fill: attrs.body.fill,
            labelText: attrs.label.text,
            labelFill: attrs.label.fill,
            height: (attrs.image && attrs.image.height) || 80,
            width: (attrs.image && attrs.image.width) || 80,
            xlinkHref: (attrs.xlinkHref && attrs.image.xlinkHref) || 'https://gw.alipayobjects.com/zos/bmw-prod/2010ac9f-40e7-49d4-8c4a-4fcf2f83033b.svg'
          }
          return this.editDrawer = true;
        }
        // 编辑连线
        if(!cell.isNode() && cell.shape === 'edge') {
          this.editTitle = this.$t('common.label.editConnection');
          this.form = {
            label: (cell.labels && cell.labels[0]) ? cell.labels[0].attrs.labelText.text : '',
            stroke: cell.attrs.line.stroke || '',
            connector: 'rounded',
            strokeWidth: cell.attrs.line.strokeWidth || '',
            isArrows: cell.attrs.line.sourceMarker ? true : false,
            isAnit: cell.attrs.line.strokeDasharray ? true : false,
            isTools: false,
          }
          // 看连线上是否有label
          const edgeCellLabel = cell.labels && cell.labels[0] && cell.labels[0].attrs || false;
          if(this.form.label && edgeCellLabel) {
            this.labelForm = {
              fontColor: edgeCellLabel.labelText.fill || '#333',
              fill: edgeCellLabel.labelBody.fill || '#fff',
              stroke: edgeCellLabel.labelBody.stroke || '#555'
            }
          } else {
            this.labelForm = { fontColor:'#333', fill:'#FFF', stroke:'#555' };
          }
          return this.editDrawer = true;
        }
      },
      // 关闭编辑节点表单
      closeEditForm() {
        this.editDrawer = false;
        if(this.selectCell) this.selectCell.removeTools();
      },
      // 修改一般节点
      changeNode(type, value) {
        switch (type) {
          case 'labelText':
            this.selectCell.attr('label/text', value);
            break;
          case 'fontSize':
            this.selectCell.attr('label/fontSize', value);
            break;
          case 'fontFill':
            this.selectCell.attr('label/fill', value);
            break;
          case 'fill':
            this.selectCell.attr('body/fill', value);
            break;
          case 'stroke':
            this.selectCell.attr('body/stroke', value);
            break;
        }
      },
      // 修改图片节点
      changeImageNode(type, value) {
        switch (type) {
          case 'labelText':
            this.selectCell.attr('label/text', value);
            break;
          case 'labelFill':
            this.selectCell.attr('label/fill', value);
            break;
          case 'fill':
            this.selectCell.attr('body/fill', value);
            break;
          case 'xlinkHref':
            this.selectCell.attr('image/xlinkHref', value);
            break;
          case 'height':
            this.selectCell.attr('image/height', value);
            break;
          case 'width':
            this.selectCell.attr('image/width', value);
            break;
        }
      },
      // 修改边label属性
      changeEdgeLabel(label, fontColor, fill, stroke) {
        this.selectCell.setLabels([configEdgeLabel(label, fontColor, fill, stroke)]);
        if(!label) {
          this.labelForm = { fontColor: '#333', fill: '#FFF', stroke: '#555' }
        }
      },
      // 修改边的颜色
      changeEdgeStroke(val) {
        this.selectCell.attr('line/stroke', val);
      },
      // 修改边的样式
      changeEdgeConnector(val) {
        switch (val) {
          case 'normal':
            this.selectCell.setConnector(val);
            break;
          case 'smooth':
            this.selectCell.setConnector(val);
            break;
          case 'rounded':
            this.selectCell.setConnector(val, { radius: 20 });
            break;
          case 'jumpover':
            this.selectCell.setConnector(val, { radius: 20 });
            break;
        }
      },
      // 修改边的宽度
      changeEdgeStrokeWidth(val) {
        if(this.form.isArrows) {
          this.selectCell.attr({
            line: {
              strokeWidth: val,
              sourceMarker: {
                width: 12 * (val / 2) || 12,
                height: 8 * (val / 2) || 8
              },
              targetMarker: {
                width: 12 * (val / 2) || 12,
                height: 8 * (val / 2) || 8
              }
            }
          })
        } else {
          this.selectCell.attr({
            line: {
              strokeWidth: val,
              targetMarker: {
                width: 12 * (val / 2) || 12,
                height: 8 * (val / 2) || 8
              }
            }
          })
        }
      },
      // 修改边的箭头
      changeEdgeArrows(val) {
        if(val) {
          this.selectCell.attr({
            line: {
              sourceMarker: {
                name: 'block',
                width: 12 * (this.form.strokeWidth / 2) || 12,
                height: 8 * (this.form.strokeWidth / 2) || 8
              },
              targetMarker: {
                name: 'block',
                width: 12 * (this.form.strokeWidth / 2) || 12,
                height: 8 * (this.form.strokeWidth / 2) || 8
              },
            }
          })
        } else {
          this.selectCell.attr({
            line: {
              sourceMarker: '',
              targetMarker: {
                name: 'block',
                size: 10 * (this.form.strokeWidth / 2) || 10
              },
            }
          })
        }
      },
      // 修改边的添加蚂蚁线
      changeEdgeAnit(val) {
        if(val){
          this.selectCell.attr({
            line: {
              strokeDasharray: 5,
              style: {
                animation: 'ant-line 30s infinite linear',
              }
            }
          });
        } else {
          this.selectCell.attr({
            line: {
              strokeDasharray: 0,
              style: {
                animation: '',
              }
            }
          });
        }
      },
      // 给线添加调节工具
      changeEdgeTools(val) {
        if(val) {
          this.selectCell.addTools(['vertices', 'segments'])
        }
        else {
          this.selectCell.removeTools();
        }
      },
      // 删除节点
      handlerDel() {
        this.$confirm(this.$t('common.prompt.info.isConfirmDelnode'), this.$t('common.dialog.tip'), {
          confirmButtonText: this.$t('common.dialog.confirm'),
          cancelButtonText: this.$t('common.dialog.cancel'),
          type: 'warning'
        }).then(() => {
          const cells = this.graph.getSelectedCells();  // 获取选中的节点
          if (cells.length) {
            this.graph.removeCells(cells);              // 清空选中的节点
            this.form = {};                             // 清空表单内容
            this.editDrawer = false;                    // 关闭组件编辑区
            this.delManyConfig(cells);                  // 删除节点配置
            this.resetLocation();                       // 重新调整布局
            this.reStatisticsExpectedWorkingHours();    // 重新统计预计工作时长
            this.$message({type: 'success',message: this.$t('common.prompt.success.del')});
          }
        }).catch(() => {})
      },
      // 导出
      handlerSend() {
        const {cells: jsonArr} = this.graph.toJSON();
        let graphData = JSON.stringify(jsonArr);
        this.$emit('finish', graphData);
        //console.log(graphData);

        if(graphData === "[]") {
          this.$message({type: 'error',message: this.$t('common.prompt.error.configureAtLeastOneNode')});
          return;
        }

        // 获取节点配置顺序数据
        let nodeData = [];
        jsonArr.filter(function(item) {
          try {
            if (item.data.type = "otherImage") {
              nodeData.push({
                NodeId: item.id,
                NodeName: item.attrs.label.tag,
                NodeCreateTime: item.createTime,
              });
            }
          } catch {}
        });
        //console.log(nodeData);

        // 获取全部配置参数
        let ids = jsonArr.map(item => { return item.id; });
        let nodeConfig = this.dialogSaveForm.filter(function(item) { return ids.includes(item.id); });
        // console.log(nodeConfig);
        // return;

        // 校验必填项
        this.$refs["form"].validate(async (valid) => {
          // 如果表单校验成功时执行
          if (valid) {

            // 打开加载框
            this.isLoading = true;

            let data = {};

            // 如果ID为空则为新增，否则为编辑
            if (this.templateid == undefined) {
              data = {
                ExpTemplateData: {
                  Type: this.basicform.type,
                  Name: this.basicform.templateName,
                  Number: this.basicform.number,
                  Sort: 1,
                  Remark: ""
                },
                ExpTemplateConfigData: {
                  Type: this.basicform.taskType,
                  ExpectedWorkingHours: parseInt(this.basicform.expectedWorkingHours),
                  FlowPathConfig: graphData,
                  AssemblyConfig: JSON.stringify(nodeConfig),
                  Remark: ""
                },
                NodeConfigData: nodeConfig,
                ExpConfigNodeData: nodeData,
              };

              // // 测试：查看已生成的表单内容，不提交数据
              // console.log(data)
              // return;

              await SubmitExperimentTemplate(data).then(res => {
                this.isLoading = false;   // 关闭加载框
                if (res.success) {
                  this.$message({type: 'success', message: this.$t('common.prompt.success.submit')});
                  this.cancel();
                } else {
                  this.$message({type: 'error', message: res.msg});
                }
              });
            } else {
              // 如果当前实验模板ID不为空，实验流程ID为空时，代表当前模板不存在此类型的流程数据，直接新增流程
              if (this.templateid != undefined && this.id == "undefined") {
                data = {
                  ExpTemplateConfigData: {
                    ExpTemplateId: this.templateid,
                    Type: this.basicform.taskType,
                    ExpectedWorkingHours: parseInt(this.basicform.expectedWorkingHours),
                    FlowPathConfig: graphData,
                    AssemblyConfig: JSON.stringify(nodeConfig),
                    Remark: ""
                  },
                  NodeConfigData: nodeConfig,
                  ExpConfigNodeData: nodeData,
                };

                // // 测试：查看已生成的表单内容，不提交数据
                // console.log(data)
                // return;

                await SubmitExperimentTemplateConfig(data).then(res => {
                  this.isLoading = false;   // 关闭加载框
                  if (res.success) {
                    this.$message({type: 'success', message: this.$t('common.prompt.success.submit')});
                    this.cancel();
                  } else {
                    this.$message({type: 'error', message: res.msg});
                  }
                });
              } else {
                data = {
                  ExpTemplateData: {
                    Id: this.templateid,
                    Type: this.basicform.type,
                    Name: this.basicform.templateName,
                    Number: this.basicform.number,
                    Sort: 1,
                    Remark: ""
                  },
                  ExpTemplateConfigData: {
                    Id: this.id,
                    Type: this.basicform.taskType,
                    ExpectedWorkingHours: parseInt(this.basicform.expectedWorkingHours),
                    FlowPathConfig: graphData,
                    AssemblyConfig: JSON.stringify(nodeConfig),
                    Remark: ""
                  },
                  NodeConfigData: nodeConfig,
                  ExpConfigNodeData: nodeData,
                };

                // // 测试：查看已生成的表单内容，不提交数据
                // console.log(data)
                // return;

                await SubmitExperimentTemplate(data).then(res => {
                  this.isLoading = false;   // 关闭加载框
                  if (res.success) {
                    this.$message({type: 'success', message: this.$t('common.prompt.success.submit')});
                    this.cancel();
                  } else {
                    this.$message({type: 'error', message: res.msg});
                  }
                });
              }
            }
          }
        });
      },
      // 返回事件
      cancel() {
        this.$router.back();
      },

      // ======================================== 工具相关 ========================================

      // 将英文名称转换为表单项的Key
      // 规则：提取第一个字符并将其转换为小写, 去除所有空格
      toLowerCaseFirstLetter(str) {
        // 如果字符串为空或只有一个字符，直接返回原字符串
        if (str.length === 0) return str;
        // 提取第一个字符并将其转换为小写
        let firstChar = str.charAt(0).toLowerCase();
        // 提取剩余部分（如果有的话）
        let remaining = str.slice(1);
        // 合并首字母和剩余部分
        return firstChar + remaining;
      }
    }
  }
</script>
<style lang="scss">
@keyframes ant-line {
  to {
    stroke-dashoffset: -1000
  }
}
</style>
<style lang="scss" scoped="scoped">
/*基本样式*/
.assembly-main {
  width: 140px;
  height: 140px;
  text-align: center;
  margin: 5px;
  border-style: solid;
  border-width: 2px;
  border-color: #f2f2f2;
  border-radius: 10px;
  box-shadow: 4px 4px 15px #f2f2f2;
}
.assembly-main img {
  width: 100px;
  height: 100px;
  padding: 2%;
  margin-top: 1%;
}

// 区域标题样式
.titie-bar {
  width: 4px;
  height: 32px;
  border-radius: 2px;
  background-color: rgba(61, 171, 175, 1);
  margin: 5px 0 5px 0;
}

.titie-bar span {
  color: #0A0A0A;
  width: 80px;
  font-size: 22px;
  line-height: 32px;
  white-space: nowrap;
  overflow-wrap: break-word;
  margin-left: 15px;
}

/*提示框基本样式*/
.dialog_div {
  ::v-deep .el-dialog__wrapper {
    .el-dialog {
      overflow: hidden;
      height: 40%;
      .el-dialog__body {padding: 30px 20px;}
      .el-dialog__header {padding: 0px;}
      .el-dialog__headerbtn {top: 5px;right: 5px;padding-top: 10px;}
      .el-dialog__headerbtn .el-dialog__close {color: #fff;height: 30px;width: 35px;}
      .el-dialog__headerbtn .el-dialog__close:hover {color: gray;}
    }
  }
}

/*对话框框架*/
::v-deep .el-card__body {padding: 10px;}
::v-deep .el-dialog__headerbtn {font-size: 22px; margin-top: -8px;}
::v-deep .el-dialog__headerbtn .el-dialog__close {color: #FFF;}

/*空状态框架*/
::v-deep .el-empty__image {text-align: center;margin-left: auto;margin-right: auto;}
::v-deep .el-empty__description {color: #AAAAAA;}

.dialog-content {
  ::v-deep .el-row {
    margin-bottom: 20px;
    &:last-child {
      margin-bottom: 0;
    }
  }
  ::v-deep .el-col {border-radius: 4px;}
  ::v-deep .el-switch {margin-bottom: 3px;}
}

/*编辑器区域样式*/
.all{
  border-radius: 8px;
  overflow: hidden;
}
.antv-content{
  background: #fff;
  display: flex;
  overflow: hidden;
  position: relative;
  .antv-menu{
    width: 200px;
    border-right: 1px solid #d5d5d5;
    padding: 10px;
    h3 {padding: 10px;}
    li{
      padding: 10px;
      border-radius: 8px;
      border: 1px solid #555;
      background: #fff;
      margin: 5px 10px;
      font-size: 12px;
      display: flex;
      align-items: center;
      cursor: pointer;
      transition: all 0.5s ease;
      &:hover {box-shadow: 0 0 5px rgba($color: #000000, $alpha: 0.3);}
      i {font-size: 18px; margin-right: 10px;}
      strong {flex: 1;}
    }
  }
  .antv-wrapper{
    flex: 1;
    position: relative;
    .wrapper-canvas{position: relative; height: 800vh; min-height: 720px;}
    .wrapper-tips{
      padding: 10px;
      display: flex;
      align-items: center;
      position: absolute;
      top: 0;
      left: 0;
      .wrapper-tips-item {
        span {padding-left: 10px;font-size: 12px;}
      }
    }
  }
}
i.icon-oval {display: inline-block; width: 16px; height: 10px; border-radius: 10px; border: 2px solid #555;}
i.icon-square {display: inline-block; width: 16px; height: 10px; border: 2px solid #555;}
i.icon-ysquare {display: inline-block; width: 16px; height: 10px; border-radius: 4px; border: 2px solid #555;}
i.icon-rhombus {display: inline-block; width: 10px; height: 10px; border: 2px solid #555; transform: rotate(45deg);}
i.icon-rhomboid {display: inline-block; width: 10px; height: 10px; border: 2px solid #555; transform: skew(-30deg);}
i.icon-circle {display: inline-block; width: 16px; height: 16px; border-radius: 16px; border: 2px solid #555;}
.edit-main{
  position: absolute;
  right: 0;
  top: 0;
  height: 100%;
  width: 100%;
  border-left: 1px solid #f2f2f2;
  box-shadow: 0 -10px 10px rgba($color: #000000, $alpha: 0.3);
  padding: 20px;
  background: #fff;
  box-sizing: border-box;
  .edit-main-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    h3 {flex: 1;}
    i {
      cursor: pointer;
      font-size: 20px;
      opacity: 0.7;
      &:hover{opacity: 1;}
    }
  }
  .form-main {
    padding: 20px 0;
    .label-style {
      background: #f2f2f2;
      padding: 0 10px;
      p {display: flex; align-items: center; font-size: 12px;}
    }
  }
  .edit-btn {}
  .see-box{
    padding: 20px;
    background: #f2f2f2;
    h5 {padding-bottom: 10px;}
    .see-item {padding: 10px 30px; border: 2px solid #333; text-align: center;}
  }
}
.wrapper-btn {
  text-align: center;
  padding: 10px;
  button {width: 100%;}
}
</style>
